package unite;


import java.io.Serializable;
import java.util.Iterator;

import java.util.Collection;

import javax.swing.JOptionPane;

import regles.Regle;
import regles.TypeScenario;


/**
 * Objet représentant un Pokémon, en général. 
 * @author Alexis BRASY, Geoffrey LEQUESNE, Sandrine PIRIOU, Michel POPOV
 *
 */
public abstract class Pokemon extends Jouable implements Serializable {
    private static final long serialVersionUID = 1L;
	
    /** Déplacement restant une fois que l'unité est morte. */
    protected int deplacementPostMortem;

    /** Expérience obtenue par le Pokémon */
    protected int xp;
	
    /**
     * Renvoie le type du Pokémon.
     * @return type 
     */
    public abstract TypeUnite getType();

    /**
     * Renvoie l'expérience du Pokémon.
     * @return xp
     */
    public int getXp() {
        if (xp > 0) {
            return xp;
        } else if (xp == 0) {
            return 1;
        }
        assert false;
        return 1;
    }

    /**
     * Modifie l'expérience.
     * @param xp
     */
    public void setXp(int xp) {
        this.xp = xp;
    }
	
    /**
     * Réinitialise le tour d'un pokemon
     * met les déplacements à leur valeur initiale
     */
    @Override
    public void initTour() {
        int dep = getRegles().getCaracUnite(this.getType(),
                TypeCarac.DEPLACEMENT);

        if (estPresqueMort()) {
            
            dep = Math.min(dep, deplacementPostMortem);
        }
		
        this.setDeplacement(dep);
    }
	
    /**
     * Réduit le nombre de points de déplacement restants dans le cas ou le Pokémon est presque mort 
     */
    public void deplacement(int dep) {
        if (estPresqueMort()) {
            deplacementPostMortem -= dep;
        }
        if (deplacementPostMortem <= 0 && estPresqueMort()) {
            tuer();
            JOptionPane.showMessageDialog(null,
                    "Votre unité viens de succomber.\nElle était trop vieille.",
                    "Information", JOptionPane.INFORMATION_MESSAGE);
        }
    }
	
    @Override
    public int gainXP(Unite attaque) {
        if (attaque.estPokemon() || attaque.getType() == TypeUnite.DRESSEUR) {
            boolean etaitPresqueMort = estPresqueMort();

            
            int tmp = xp;
            // Niveaux d'évolution des pokémons 
            // 1 : 0-49
            // 2 : 50 - 149
            // 3 : + 150
            // On ne prend pas en compte l'unité presque morte comme un palier
            int nivEvolAttaque = 1, nivEvolAttaquant = 1;
            Collection<Integer> colNivEvol = attaque.getCaseTerrain().getTerrain().getRegles().getPaliersEvolution();
            int[] nivEvol = new int[colNivEvol.size()];
            Iterator<Integer> it = colNivEvol.iterator();

            for (int i = 0; i < colNivEvol.size(); i++) {
                nivEvol[i] = ((Integer) it.next()).intValue();
            }
			
            for (int i = 0; i < colNivEvol.size() - 1; i++) {
                if (attaque.getXp() >= nivEvol[i]) {
                    nivEvolAttaque++;
                }
                if (this.getXp() >= nivEvol[i]) {
                    nivEvolAttaquant++;
                }
            }
            xp += (int) (50
                    * ((float) nivEvolAttaque / (float) nivEvolAttaquant)
                    * (1 + 0.5
                    - this.getRegles().getFacteurImpact(this.getType(),
                    attaque.getType()))
                    * (1 + this.getChance()));
            // xp += (40*(1+this.getRegles().getFacteurImpact(attaque.getType(),this.getType()))*(attaque.getNiveau()+1))*(this.getChance());
            int win = xp - tmp;

            
			
            if (etaitPresqueMort == false && estPresqueMort() == true) {
                deplacementPostMortem = getRegles().getDepPostMortem();
                
            }
            return win;
        } else {
            return 0;
        }
    }

    @Override
    public int getNiveau() {
        Collection<Integer> c = (new Regle(TypeCombat.ASSAUT, TypeScenario.GOTTAKILLTHEMALL, 0, 2, 3, 2)).getPaliersEvolution();
        Iterator<Integer> i = c.iterator();
        int niv = 0;

        while (i.hasNext()) {
            if (this.getXp() > i.next()) {
                niv++;
            }
        }
        return niv;
    }

    /**
     * Méthode à appeler en fin de tour, pour régénérer les PV en fonction des règles, si le pokémon ne s'est pas déplacé
     */
    public void regenPVfinTour() {
        if (deplacement
                == getRegles().getCaracUnite(this.getType(),
                TypeCarac.DEPLACEMENT)) {
            pv += getRegles().getRegenPV();
			
            int pvMax = getRegles().getCaracUnite(this.getType(), TypeCarac.PV);

            if (pv > pvMax) {
                pv = pvMax;
            }
        }
    }
}
